import template from "../template";
import { $html } from "../utils";

/**
 * 公共区域计算 (页首页尾)
 * @param {*} options
 */
const publicArea = function (options, item, type) {
  if (!["header", "footer"].includes(type)) {
    return "";
  }
  // 传入字符串则直接返回字符串，传入函数则调用函数并传入每页循环产生的参数
  if (options[type] && typeof options[type] === "string") {
    return template[type].replace("##", options[type]);
  } else if (options[type] && typeof options[type] === "function") {
    return template[type].replace("##", options[type](item));
  }
  return template[type].replace("##", "");
};

/**
 * 页首计算
 * @param {*} options
 */
const headerCompute = function (options, item) {
  return publicArea(options, item, "header");
};

/**
 * 页尾计算
 * @param {*} options
 */
const footerCompute = function (options, item) {
  return publicArea(options, item, "footer");
};

// 总内容
let totalPages = [];

// 当前页内容
let current = {};

/**
 * 内容计算
 * @param {*} options
 */
const contentCompute = function (page, options, rowSpan) {
  // 打印区域高度
  const iframeHeight = options.$iframe.offsetHeight;
  // 页首
  const header = headerCompute(options, current);
  const headerHeight = $html(header).rect.height;
  // 页尾
  const footer = footerCompute(options, current);
  const footerHeight = $html(footer).rect.height;
  // 内容最大高度
  const contentHeight =
    iframeHeight -
    headerHeight -
    footerHeight -
    current.theadHeight -
    current.tfootheight;
  /* 拿到tbody,获取里边的所有tr,向页面中追加,同时获取tr的高度,累计高度大于最大值时则开启新页面,直到所有tr追加完毕 */
  const currentPageTable = [];
  let outerHtml = "";
  let currentTrHeight = 0;
  // 拿出当前页可以渲染的tr
  for (let index = 0; index < current.trlist.length; index++) {
    const tr = current.trlist[index];
    const trHeight = tr.offsetHeight;
    currentTrHeight += trHeight;
    // 追加前截断
    if (currentTrHeight > contentHeight) {
      break;
    }
    currentPageTable.push(tr);
  }

  // 包含行合并属性的td
  const hasSpanTd = [];
  // 操作tr,处理跨页行合并
  currentPageTable.forEach((tr, index) => {
    const tdlist = tr.getElementsByTagName("td");
    if (Array.isArray(rowSpan) && rowSpan.length && index === 0) {
      let innerHtml = "";
      rowSpan.forEach((item) => {
        if (item) {
          item.el.rowSpan = item.span;
          innerHtml += item.el.outerHTML;
        } else {
          if (tr.firstElementChild) {
            innerHtml += tr.firstElementChild.outerHTML;
            tr.removeChild(tr.firstElementChild);
          }
        }
      });
      outerHtml += innerHtml;
    } else {
      for (let i = 0; i < tdlist.length; i++) {
        const td = tdlist[i];
        // 得出行合并溢出的元素
        if (td.rowSpan > 1 && td.rowSpan + index > currentPageTable.length) {
          // 向溢出位置添加溢出的行数
          hasSpanTd[i] = {
            span: td.rowSpan + index - currentPageTable.length,
            el: td.cloneNode(false),
          };
        } else if (!hasSpanTd[i]) {
          // 填充其余内容
          hasSpanTd[i] = null;
        }
      }
      outerHtml += tr.outerHTML;
    }
  });

  // 封装内容部分
  const body = template.body.replace(
    "##",
    current.template.replace("##", outerHtml)
  );
  totalPages.push({ body });

  // 删除已经渲染的tr并开始下一页递归
  current.trlist.splice(0, currentPageTable.length);
  if (current.trlist.length) {
    contentCompute(page, options, hasSpanTd);
  }
};

export default (page, options, callback) => {
  // 清除上次执行的缓存
  totalPages = [];
  // 初始化当前操作对象
  current = {
    pageNo: 0,
    theadHeight: 0,
    tfootheight: 0,
    theadEl: null,
    tbodyEl: null,
    tfootEl: null,
    template: "",
    total: 0,
    trlist: [],
  };
  // 渲染表格到iframe
  const div = document.createElement("div");
  div.innerHTML = template.html
    .replace("##", options.sizeStyle + options.body)
    .replace(
      "#htmlPrintCss#",
      `<link rel="stylesheet" href="${
        options.htmlPrintCss || "browser-table-print.css"
      }" />`
    );
  options.$iframe.contentDocument.body.appendChild(div);
  const link = options.$iframe.contentDocument.querySelectorAll("link")[0];
  link.onload = () => {
    // 获取thead,tfoot的高度
    const thead = div.getElementsByTagName("thead")[0];
    const tfoot = div.getElementsByTagName("tfoot")[0];
    thead && (current.theadHeight = thead.offsetHeight);
    tfoot && (current.tfootheight = tfoot.offsetHeight);
    current.theadEl = thead;
    current.tbodyEl = div.getElementsByTagName("tbody")[0];
    current.tfootEl = tfoot;
    // 提取出所有tr
    const trlist = current.tbodyEl.getElementsByTagName("tr");
    for (let i = 0; i < trlist.length; i++) {
      const tr = trlist[i];
      current.trlist.push(tr);
    }
    // 锁定每个td的宽度
    let tdWidth = "";
    const firstTr = trlist[0];
    if (firstTr) {
      const tds = firstTr.getElementsByTagName("td");
      for (let i = 0; i < tds.length; i++) {
        const _td = tds[i];
        tdWidth += `tr>td:nth-child(${i + 1}){width:${_td.offsetWidth}px}`;
      }
    }
    const tdStyle = `<style>${tdWidth}</style>`;
    // 复制一份div建立模板
    const cdiv = div.cloneNode(true);
    cdiv.getElementsByTagName("tbody")[0].innerHTML = "##";
    current.template = cdiv.innerHTML;
    // 执行内容计算
    contentCompute(page, options);
    // 完成后修改总页数
    current.total = totalPages.length;
    // 更新视图并生成最终结果
    totalPages.forEach((item, index) => {
      const pageCurrent = { ...current, pageNo: index + 1 };
      const header = headerCompute(options, pageCurrent);
      const footer = footerCompute(options, pageCurrent);
      item.content = page.replace(
        "##",
        `${header}${tdStyle}${item.body}${footer}`
      );
    });
    callback && callback(totalPages);
  };
};
